﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;
using System.Windows.Input;
using System;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.Enums;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;
using System.Collections.Generic;
using SHomeWorkshop.LunarMind;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月20日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：三角形部件。
    /// </summary>
    public class TriangleWidget : ShapeWidget, ICanBeLinkedWidget, Widgets.Interfaces.ITextRotate
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态构造方法]
        /// </summary>
        static TriangleWidget()
        {
            dashArray = new DoubleCollection() { 2, 2 };
        }

        /// <summary>
        /// [构造方法]
        /// </summary>
        public TriangleWidget(PageEditorReader masterEditor)
            : base(masterEditor)
        {
            widgetType = Enums.WidgetTypes.Triangle;
            widgetClassLocalName = Widget.GetWidgetClassLocalName(this.GetType().Name);

            this.mainPath.Data = this.pathGeometry;
            this.pathGeometry.Figures.Add(this.pathFigure);
            this.pathFigure.Segments.Add(this.arcSegmentAtInner);
            this.pathFigure.Segments.Add(this.startLineSegment);
            this.pathFigure.Segments.Add(this.arcSegmentAtOuter);
            this.pathFigure.Segments.Add(this.endLineSegment);

            mainPath.Fill = null;
            mainPath.Stroke = WidgetForeColor;

            this.mainCanvas.Children.Add(mainPath);

            Canvas.SetZIndex(mainPath, 0);

            this.commentAdorner = new CommentAdorner(this.mainPath, this) { Visibility = System.Windows.Visibility.Collapsed };//默认不显示。

            this.hyperLinkAdorner = new HyperLinkAdorner(this.mainPath, this) { Visibility = Visibility.Collapsed };
            this.hyperLinkAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(hyperLinkAdorner_MouseLeftButtonUp);

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainCanvas);
            if (adornerLayer == null)
            {
                MessageBox.Show("　　未找到Widget的装饰层！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            else
            {
                adornerLayer.Add(this.commentAdorner);//这个要在各具体部件类中添加。
                adornerLayer.Add(this.hyperLinkAdorner);//这个要在各具体部件类中添加。
            }
            
            //最后添加文本面板。
            this.mainCanvas.Children.Add(this.mainTextPanel);
            Canvas.SetZIndex(this.mainTextPanel, 2);
        }

        #endregion


        #region 字段与属性===================================================================================================

        public override Point BottomRight
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(Math.Min(startPoint.X, endPoint.X), centerCPPoint.X);
                maxRight = Math.Max(Math.Max(startPoint.X, endPoint.X), centerCPPoint.X);

                minTop = Math.Min(Math.Min(startPoint.Y, endPoint.Y), centerCPPoint.Y);
                maxBottom = Math.Max(Math.Max(startPoint.Y, endPoint.Y), centerCPPoint.Y);

                return new Point(maxRight, maxBottom);
            }
        }
        
        private Point centerCPPoint = new Point();
        [Tools.LunarProperty("CenterCPPoint", PropertyDateType.Point)]
        public Point CenterCPPoint
        {
            get { return centerCPPoint; }
            set
            {
                centerCPPoint = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.CenterCPPointTag, value.ToString());
                }

                RefreshLocation();
            }
        }
        
        private Point endPoint = new Point();
        /// <summary>
        /// [读写]线的终点坐标。
        /// </summary>
        [Tools.LunarProperty("EndPoint", PropertyDateType.Point)]
        public Point EndPoint
        {
            get { return endPoint; }
            set
            {
                endPoint = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.EndPointTag, value.ToString());
                }

                RefreshLocation();
            }
        }

        /// <summary>
        /// [只读]表示当前部件是否被某个连接线挂接着。
        /// </summary>
        public bool IsLinked
        {
            get
            {
                if (this.masterEditor == null) return false;

                foreach (UIElement ue in this.masterEditor.Children)
                {
                    ILinkableLine linkedLine = ue as ILinkableLine;
                    if (linkedLine == null) continue;

                    if (linkedLine.StartMasterId == this.id || linkedLine.EndMasterId == this.id) return true;
                }

                return false;
            }
        }

        #region 画三角形、饼形、环形

        private Path mainPath = new Path() { Cursor = Cursors.Hand };

        private PathGeometry pathGeometry = new PathGeometry();

        private PathFigure pathFigure = new PathFigure();

        private LineSegment startLineSegment = new LineSegment();

        private LineSegment endLineSegment = new LineSegment();

        /// <summary>
        /// 三角形SE边由弧来实现。
        /// </summary>
        private ArcSegment arcSegmentAtOuter = new ArcSegment();

        private ArcSegment arcSegmentAtInner = new ArcSegment();

        #endregion

        private Rect movingRect;
        /// <summary>
        /// 部件正在被拖动时的外边框。
        /// </summary>
        public Rect MovingRect
        {
            get
            {
                return movingRect;
            }
        }
        
        private Point startPoint = new Point(0, 0);
        /// <summary>
        /// [读写]线的起点坐标。
        /// </summary>
        [Tools.LunarProperty("StartPoint", PropertyDateType.Point)]
        public Point StartPoint
        {
            get { return startPoint; }
            set
            {
                startPoint = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.StartPointTag, startPoint.ToString());
                }

                RefreshLocation();
            }
        }

        private double textRotateAngle = 0;
        /// <summary>
        /// [读写]文本旋转角度。取值范围：[-180,180]。
        /// </summary>
        [Tools.LunarProperty("TextRotateAngle", PropertyDateType.Double)]
        public double TextRotateAngle
        {
            get { return textRotateAngle; }
            set
            {
                if (value > 180)
                {
                    textRotateAngle = 180;
                }
                else if (value < -180)
                {
                    textRotateAngle = -180;
                }
                else
                {
                    textRotateAngle = value;
                }

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TextRotateAngleTag, textRotateAngle.ToString());
                }

                this.RefreshTextRotateAngle();
            }
        }

        private Enums.TriangleForm triangleForm = TriangleForm.Triangle;
        /// <summary>
        /// [读写]三角形形态。
        /// </summary>
        [Tools.LunarProperty("TriangleForm", PropertyDateType.TriangleForm)]
        public Enums.TriangleForm TriangleForm
        {
            get { return triangleForm; }
            set
            {
                triangleForm = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TriangleFormTag, triangleForm.ToString());
                }
                DrawLine();
                RefreshTextPanelLocatin();
            }
        }

        public override Point TopLeft
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(Math.Min(startPoint.X, endPoint.X), centerCPPoint.X);
                maxRight = Math.Max(Math.Max(startPoint.X, endPoint.X), centerCPPoint.X);

                minTop = Math.Min(Math.Min(startPoint.Y, endPoint.Y), centerCPPoint.Y);
                maxBottom = Math.Max(Math.Max(startPoint.Y, endPoint.Y), centerCPPoint.Y);

                return new Point(minLeft, minTop);
            }
        }

        #endregion


        #region 方法=========================================================================================================

        public override void Build()
        {
            base.Build();

            if (this.xmlData == null) return;

            XmlAttribute attrStartPoint = this.xmlData.GetAttribute(XmlTags.StartPointTag);
            if (attrStartPoint != null)
            {
                this.startPoint = Point.Parse(attrStartPoint.Value);
            }

            XmlAttribute attrCenterCPPoint = this.xmlData.GetAttribute(XmlTags.CenterCPPointTag);
            if (attrCenterCPPoint != null)
            {
                this.centerCPPoint = Point.Parse(attrCenterCPPoint.Value);
            }

            XmlAttribute attrEndPoint = this.xmlData.GetAttribute(XmlTags.EndPointTag);
            if (attrEndPoint != null)
            {
                this.endPoint = Point.Parse(attrEndPoint.Value);
            }

            XmlAttribute attrTextRotateAngle = this.xmlData.GetAttribute(XmlTags.TextRotateAngleTag);
            if (attrTextRotateAngle != null)
            {
                this.textRotateAngle = double.Parse(attrTextRotateAngle.Value);
            }

            XmlAttribute attrTriangleForm = this.xmlData.GetAttribute(XmlTags.TriangleFormTag);
            if (attrTriangleForm != null)
            {
                this.triangleForm = (Enums.TriangleForm)Enum.Parse(typeof(Enums.TriangleForm), attrTriangleForm.Value);
            }

            this.RefreshTextRotateAngle();
            this.RefreshLocation();

            //此类是下面这几个属性的“最终实现类”。这些属性的值都已在基类确定。因此调用,
            this.RefreshWidgetBackColor();
            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
            this.RefreshLineDash();
        }
        
        public void DrawLine()
        {
            if (masterEditor == null) return;

            DrawLine(this.startPoint, this.centerCPPoint, this.endPoint);
        }

        /// <summary>
        /// 三角形由三个顶点决定。
        /// </summary>
        /// <param name="startPoint">首端点。</param>
        /// <param name="centerCPPoint">中控制点。</param>
        /// <param name="endPoint">尾端点。</param>
        private void DrawLine(Point startPoint, Point centerCPPoint, Point endPoint)
        {
            Point startBasePt = new Point();
            Point endBasePt = new Point();

            startBasePt.X = Math.Min(Math.Min(startPoint.X, centerCPPoint.X), endPoint.X);
            startBasePt.Y = Math.Min(Math.Min(startPoint.Y, centerCPPoint.Y), endPoint.Y);

            endBasePt.X = Math.Max(Math.Max(startPoint.X, centerCPPoint.X), endPoint.X);
            endBasePt.Y = Math.Max(Math.Max(startPoint.Y, centerCPPoint.Y), endPoint.Y);

            //mainPolygon.Points = new PointCollection()
            //{
            //    startPoint,centerCPPoint,endPoint,startPoint,
            //};

            switch (this.triangleForm)
            {
                case Enums.TriangleForm.Triangle:
                    {
                        #region 三角形绘制代码

                        Size zeroSize = new Size(0, 0);

                        this.pathFigure.StartPoint = centerCPPoint;
                        this.arcSegmentAtInner.Point = centerCPPoint;//此时不显示内弧。
                        this.startLineSegment.Point = startPoint;
                        this.arcSegmentAtOuter.Point = endPoint;
                        this.arcSegmentAtOuter.Size = zeroSize;
                        this.endLineSegment.Point = centerCPPoint;
                        #endregion

                        LocateTextPanel(startPoint, centerCPPoint, endPoint);
                        break;
                    }
                case Enums.TriangleForm.Pie:
                    {
                        Point? c = null;
                        #region 饼形绘制代码

                        //饼形，总是取“StartPoint到CenterPoint”与“EndPoint到CenterPoint”这两个线段间长度较大的那个为半径。
                        //以CenterPoint为顶点。总是顺时针方向绘制。

                        double rSToC, rEToC, r;
                        double sXOffsetToC = startPoint.X - centerCPPoint.X;
                        double sYOffsetToC = startPoint.Y - centerCPPoint.Y;
                        rSToC = Math.Sqrt(sXOffsetToC * sXOffsetToC + sYOffsetToC * sYOffsetToC);
                        double eXOffsetToC = endPoint.X - centerCPPoint.X;
                        double eYOffsetToC = endPoint.Y - centerCPPoint.Y;
                        rEToC = Math.Sqrt(eXOffsetToC * eXOffsetToC + eYOffsetToC * eYOffsetToC);

                        Point realStartPt; Point realEndPt;
                        if (rSToC > 0 && rEToC > 0)
                        {
                            this.mainPath.Visibility = System.Windows.Visibility.Visible;
                            if (rSToC > rEToC)
                            {
                                r = rSToC;
                                realStartPt = startPoint;

                                double k = rSToC / rEToC;
                                double x = centerCPPoint.X + (endPoint.X - centerCPPoint.X) * k;
                                double y = centerCPPoint.Y + (endPoint.Y - centerCPPoint.Y) * k;
                                realEndPt = new Point(x, y);

                                c = new Point(realStartPt.X + (realEndPt.X - realStartPt.X) / 2,
                                       realStartPt.Y + (realEndPt.Y - realStartPt.Y) / 2);
                            }
                            else
                            {
                                r = rEToC;
                                realEndPt = endPoint;

                                double k = rEToC / rSToC;
                                double x = centerCPPoint.X + (startPoint.X - centerCPPoint.X) * k;
                                double y = centerCPPoint.Y + (startPoint.Y - centerCPPoint.Y) * k;
                                realStartPt = new Point(x, y);

                                c = new Point(realStartPt.X + (realEndPt.X - realStartPt.X) / 2,
                                       realStartPt.Y + (realEndPt.Y - realStartPt.Y) / 2);
                            }
                            Size zeroSize = new Size(0, 0);
                            this.pathFigure.StartPoint = centerCPPoint;
                            this.arcSegmentAtInner.Size = zeroSize;
                            this.arcSegmentAtInner.Point = centerCPPoint;
                            this.startLineSegment.Point = realStartPt;
                            this.arcSegmentAtOuter.Size = new Size(r, r);
                            this.arcSegmentAtOuter.SweepDirection = SweepDirection.Clockwise;
                            this.arcSegmentAtOuter.IsLargeArc = LargeArc(startPoint, centerCPPoint, endPoint);
                            this.arcSegmentAtOuter.Point = realEndPt;
                            this.endLineSegment.Point = centerCPPoint;
                        }
                        else
                        {
                            this.mainPath.Visibility = System.Windows.Visibility.Hidden;
                        }

                        #endregion

                        if (c != null && c.HasValue)
                        {
                            Canvas.SetLeft(this.mainTextPanel, c.Value.X - this.mainTextPanel.ActualWidth / 2);
                            Canvas.SetTop(this.mainTextPanel, c.Value.Y - this.mainTextPanel.ActualHeight / 2);
                        }

                        break;
                    }
                case Enums.TriangleForm.Sector:
                    {
                        Point? c = null;

                        #region 环形绘制代码

                        //环形，总是取“StartPoint到CenterPoint”与“EndPoint到CenterPoint”这两个线段间长度间距为环径。
                        //以CenterPoint为顶点。总是顺时针方向绘制。

                        double rSToC, rEToC, outerR, innerR;

                        double sXOffsetToC = startPoint.X - centerCPPoint.X;
                        double sYOffsetToC = startPoint.Y - centerCPPoint.Y;
                        rSToC = Math.Sqrt(sXOffsetToC * sXOffsetToC + sYOffsetToC * sYOffsetToC);

                        double eXOffsetToC = endPoint.X - centerCPPoint.X;
                        double eYOffsetToC = endPoint.Y - centerCPPoint.Y;
                        rEToC = Math.Sqrt(eXOffsetToC * eXOffsetToC + eYOffsetToC * eYOffsetToC);

                        Point outerStartPt, outerEndPt, innerStartPt, innerEndPt;
                        if (rSToC > 0 && rEToC > 0)
                        {
                            this.mainPath.Visibility = System.Windows.Visibility.Visible;
                            if (rSToC > rEToC)
                            {
                                outerR = rSToC;
                                innerR = rEToC;
                                outerStartPt = startPoint;

                                double ke = rSToC / rEToC;
                                double xe = centerCPPoint.X + (endPoint.X - centerCPPoint.X) * ke;
                                double ye = centerCPPoint.Y + (endPoint.Y - centerCPPoint.Y) * ke;
                                outerEndPt = new Point(xe, ye);

                                double ks = rEToC / rSToC;
                                double xs = centerCPPoint.X + (startPoint.X - centerCPPoint.X) * ks;
                                double ys = centerCPPoint.Y + (startPoint.Y - centerCPPoint.Y) * ks;
                                innerStartPt = new Point(xs, ys);

                                innerEndPt = endPoint;

                                c = new Point(innerStartPt.X + (innerEndPt.X - innerStartPt.X) / 2,
                                    innerStartPt.Y + (innerEndPt.Y - innerStartPt.Y) / 2);
                            }
                            else
                            {
                                outerR = rEToC;
                                innerR = rSToC;
                                outerEndPt = endPoint;

                                double ks = rEToC / rSToC;
                                double xs = centerCPPoint.X + (startPoint.X - centerCPPoint.X) * ks;
                                double ys = centerCPPoint.Y + (startPoint.Y - centerCPPoint.Y) * ks;
                                outerStartPt = new Point(xs, ys);

                                double ke = rSToC / rEToC;
                                double xe = centerCPPoint.X + (endPoint.X - centerCPPoint.X) * ke;
                                double ye = centerCPPoint.Y + (endPoint.Y - centerCPPoint.Y) * ke;
                                innerEndPt = new Point(xe, ye);

                                innerStartPt = startPoint;

                                c = new Point(innerStartPt.X + (innerEndPt.X - innerStartPt.X) / 2,
                                    innerStartPt.Y + (innerEndPt.Y - innerStartPt.Y) / 2);
                            }

                            bool isLarge = LargeArc(outerStartPt, centerCPPoint, outerEndPt);

                            this.pathFigure.StartPoint = innerEndPt;

                            this.arcSegmentAtInner.Size = new Size(innerR, innerR);
                            this.arcSegmentAtInner.SweepDirection = SweepDirection.Counterclockwise;
                            this.arcSegmentAtInner.IsLargeArc = isLarge;
                            this.arcSegmentAtInner.Point = innerStartPt;

                            this.startLineSegment.Point = outerStartPt;

                            this.arcSegmentAtOuter.Size = new Size(outerR, outerR);
                            this.arcSegmentAtOuter.SweepDirection = SweepDirection.Clockwise;
                            this.arcSegmentAtOuter.IsLargeArc = isLarge;
                            this.arcSegmentAtOuter.Point = outerEndPt;

                            this.endLineSegment.Point = innerEndPt;
                        }
                        else
                        {
                            this.mainPath.Visibility = System.Windows.Visibility.Hidden;
                        }

                        #endregion

                        if (c != null && c.HasValue)
                        {
                            Canvas.SetLeft(this.mainTextPanel, c.Value.X - this.mainTextPanel.ActualWidth / 2);
                            Canvas.SetTop(this.mainTextPanel, c.Value.Y - this.mainTextPanel.ActualHeight / 2);
                        }

                        break;
                    }
            }

            //移动部件控制点时，要刷新连接线的。
            this.movingRect = new Rect(startBasePt, endBasePt);
        }

        private bool LargeArc(Point startPoint, Point centerCPPoint, Point endPoint)
        {
            if (startPoint.X == centerCPPoint.X)
            {
                if (startPoint.Y >= centerCPPoint.Y)
                {
                    if (endPoint.X >= startPoint.X) return true;
                    else return false;
                }
                else
                {
                    if (endPoint.X >= startPoint.X) return false;
                    else return true;
                }
            }
            else if (startPoint.Y == centerCPPoint.Y)
            {
                if (startPoint.X >= centerCPPoint.X)
                {
                    if (endPoint.Y > startPoint.Y) return false;
                    else return true;
                }
                else
                {
                    if (endPoint.Y > startPoint.Y) return true;
                    else return false;
                }
            }

            //分象限
            //一、四象限，E点在SC线上侧需要大弧，而下侧需要小弧
            //二、三象限，E点在SC线上侧需要小弧，而下侧需要大弧
            if (startPoint.X < centerCPPoint.X)//二、三象限
            {
                double k = (startPoint.Y - centerCPPoint.Y) / (startPoint.X - centerCPPoint.X);

                double y = endPoint.X * k + centerCPPoint.Y - k * centerCPPoint.X;
                if (endPoint.Y > y) return true;
                else return false;
            }
            else//一、四象限
            {
                double k = (startPoint.Y - centerCPPoint.Y) / (startPoint.X - centerCPPoint.X);

                double y = endPoint.X * k + centerCPPoint.Y - k * centerCPPoint.X;
                if (endPoint.Y > y) return false;
                else return true;
            }
        }

        /// <summary>
        /// 重定文本位置。
        /// </summary>
        /// <param name="startPoint">首端点。</param>
        /// <param name="centerCPPoint">中控制点。</param>
        /// <param name="endPoint">尾端点。</param>
        private void LocateTextPanel(Point startPoint, Point centerCPPoint, Point endPoint)
        {
            switch (this.triangleForm)
            {
                //case Enums.TriangleForm.Sector:
                //case Enums.TriangleForm.Pie:
                //这俩必须取消。因为扇形和饼形需要其它点的坐标，因此在DrawLine()方法中实现了。
                case Enums.TriangleForm.Triangle:
                    {
                        Point textStart;

                        double left, right, bottom, top;
                        left = Math.Min(Math.Min(startPoint.X, centerCPPoint.X), endPoint.X);
                        right = Math.Max(Math.Max(startPoint.X, centerCPPoint.X), endPoint.X);
                        top = Math.Min(Math.Min(startPoint.Y, centerCPPoint.Y), endPoint.Y);
                        bottom = Math.Max(Math.Max(startPoint.Y, centerCPPoint.Y), endPoint.Y);

                        textStart = new Point(left + (right - left) / 2 - (this.mainTextPanel.ActualWidth / 2) - this.mainTextPanel.Margin.Left,
                            top + (bottom - top) / 2 - (this.mainTextPanel.ActualHeight / 2) - this.mainTextPanel.Margin.Top);

                        Canvas.SetLeft(this.mainTextPanel, textStart.X);
                        Canvas.SetTop(this.mainTextPanel, textStart.Y);
                        break;
                    }
            }
        }
        
        private Point FormatStartMovingPoint(Point newInsideMovingPoint, Point endPoint)
        {
            double horizontalDistance = newInsideMovingPoint.X - endPoint.X;
            double verticalDistance = newInsideMovingPoint.Y - endPoint.Y;

            double absHD = Math.Abs(horizontalDistance);
            double absVD = Math.Abs(verticalDistance);

            if (absVD > absHD)
            {
                if (absVD > absHD * 2)
                {
                    newInsideMovingPoint = new Point(endPoint.X, newInsideMovingPoint.Y);
                }
                else
                {
                    int qua = Getquadrant(newInsideMovingPoint, endPoint);
                    switch (qua)
                    {
                        case 1:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 2:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 3:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 4:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                    endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                    }
                }
            }
            else
            {
                if (absVD * 2 < absHD)
                {
                    newInsideMovingPoint = new Point(newInsideMovingPoint.X, endPoint.Y);
                }
                else
                {
                    int qua = Getquadrant(newInsideMovingPoint, endPoint);
                    switch (qua)
                    {
                        case 1:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 2:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 3:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 4:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                    endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                    }
                }
            }

            return newInsideMovingPoint;
        }

        /// <summary>
        /// 取与自身挂接的连接线。
        /// </summary>
        /// <returns>可能返回null。</returns>
        public List<ILinkableLine> GetLinkedLines()
        {
            if (this.masterEditor == null) return null;

            List<Widget> widgets = new List<Widget>();
            widgets.Add(this);

            return this.masterEditor.GetLinkedLines(widgets);
        }

        /// <summary>
        /// 以basePoint为基础坐标，画出四象限。
        /// 取出pt在哪个象限中。
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="basePoint"></param>
        /// <returns></returns>
        private int Getquadrant(Point pt, Point basePoint)
        {
            if (pt.X > basePoint.X)
            {
                if (pt.Y > basePoint.Y)
                {
                    return 4;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                if (pt.Y > basePoint.Y)
                {
                    return 3;
                }
                else
                {
                    return 2;
                }
            }
        }

        public override string GetRelativeOuterXml(Point baseCopyTopLeft)
        {
            if (this.xmlData == null) return string.Empty;

            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseCopyTopLeft.X,
                oldStartPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.StartPointTag, newStartPoint.ToString());

            Point oldCenterCPPoint = centerCPPoint;
            Point newCenterCPPoint = new Point(oldCenterCPPoint.X - baseCopyTopLeft.X,
                oldCenterCPPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.CenterCPPointTag, newCenterCPPoint.ToString());

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseCopyTopLeft.X,
                oldEndPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.EndPointTag, newEndPoint.ToString());

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(this.xmlData.OuterXml);

            this.xmlData.SetAttribute(XmlTags.StartPointTag, oldStartPoint.ToString());
            this.xmlData.SetAttribute(XmlTags.CenterCPPointTag, oldCenterCPPoint.ToString());
            this.xmlData.SetAttribute(XmlTags.EndPointTag, oldEndPoint.ToString());
            return sb.ToString();
        }
        
        /// <summary>
        /// 这个虚方法是用以查看本部件是否在选定框的内部。
        /// 线型部件，各有各的计算办法。
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public override bool IsInRect(Rect rect)
        {
            //return base.IsInRect(rect);//这个要屏蔽。
            bool isInRect = base.IsInRect(rect);
            if (isInRect)
            {
                return true;
            }
            else
            {
                Rect virtualRect = new Rect(TopLeft, BottomRight);
                return rect.IntersectsWith(virtualRect);
            }
        }
        
        public override void RefreshLineDash()
        {
            switch (lineDash)
            {
                case LineDashType.DashType.Dash:
                    {
                        //this.mainPolygon.StrokeDashArray = LineDashType.dashCollection; break;
                        this.mainPath.StrokeDashArray = LineDashType.dashCollection; break;
                    }
                case LineDashType.DashType.DashDotDot:
                    {
                        //this.mainPolygon.StrokeDashArray = LineDashType.dashDotDotCollection; break;
                        this.mainPath.StrokeDashArray = LineDashType.dashDotDotCollection; break;
                    }
                case LineDashType.DashType.Dot:
                    {
                        //this.mainPolygon.StrokeDashArray = LineDashType.dotCollection; break;
                        this.mainPath.StrokeDashArray = LineDashType.dotCollection; break;
                    }
                case LineDashType.DashType.Solid:
                    {
                        //this.mainPolygon.StrokeDashArray = LineDashType.solidCollection; break;
                        this.mainPath.StrokeDashArray = LineDashType.solidCollection; break;
                    }
                default:
                    {
                        //this.mainPolygon.StrokeDashArray = LineDashType.dashDotCollection; break;
                        this.mainPath.StrokeDashArray = LineDashType.dashDotCollection; break;
                    }
            }
        }
        
        public override void RefreshWidgetLineWidth()
        {
            //mainPolygon.StrokeThickness = widgetLineWidth;
            mainPath.StrokeThickness = widgetLineWidth;
        }

        public override void RefreshLocation()
        {
            base.RefreshLocation();

            //mainPolygon.Points = new PointCollection(){
            //    startPoint,centerCPPoint,endPoint,startPoint,
            //};
            DrawLine();

            this.movingRect = new Rect(this.TopLeft, this.BottomRight);

            RefreshWidgetLineWidth();
            RefreshTextRotateAngle();

            this.RefreshCommentText();
            this.RefreshHyperLinkText();
        }

        public override void RefreshPointWhenGroupIn(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseTopLeft.X,
                oldStartPoint.Y - baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldCenterCPPoint = centerCPPoint;
            Point newCenterCPPoint = new Point(oldCenterCPPoint.X - baseTopLeft.X,
                oldCenterCPPoint.Y - baseTopLeft.Y);
            CenterCPPoint = newCenterCPPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseTopLeft.X,
                oldEndPoint.Y - baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshPointWhenGroupOut(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X + baseTopLeft.X,
                oldStartPoint.Y + baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldCenterCPPoint = centerCPPoint;
            Point newCenterCPPoint = new Point(oldCenterCPPoint.X + baseTopLeft.X,
                oldCenterCPPoint.Y + baseTopLeft.Y);
            CenterCPPoint = newCenterCPPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X + baseTopLeft.X,
                oldEndPoint.Y + baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshWidgetBackColor()
        {
            base.RefreshWidgetBackColor();
            if (widgetBackColor == Brushes.Transparent)
            {
                //mainPolygon.Fill = null;
                mainPath.Fill = null;
            }
            else
            {
                //mainPolygon.Fill = widgetBackColor;
                mainPath.Fill = widgetBackColor;
            }
        }

        public override void RefreshWidgetLineColor()
        {
            //this.mainPolygon.Stroke = widgetLineColor;
            this.mainPath.Stroke = widgetLineColor;
        }
        
        public override void RefreshIsShadowVisible()
        {
            base.RefreshIsShadowVisible();

            if (isShadowVisible)
            {
                //this.mainPolygon.Effect = Widget.ShadowEffect;
                this.mainPath.Effect = Widget.ShadowEffect;
            }
            else
            {
                //this.mainPolygon.Effect = null;
                this.mainPath.Effect = null;
            }
        }

        public override void RefreshTextPanelLocatin()
        {
            switch (this.triangleForm)
            {
                case Enums.TriangleForm.Triangle:
                    {
                        LocateTextPanel(this.startPoint, this.centerCPPoint, this.endPoint);
                        break;
                    }
                default:
                    {
                        DrawLine(this.startPoint, this.centerCPPoint, this.endPoint);
                        break;
                    }
            }
        }
        
        /// <summary>
        /// 刷新文本区旋转角度。
        /// </summary>
        public void RefreshTextRotateAngle()
        {
            if (this.mainTextPanel.RenderTransformOrigin != DefaultRenderCenter)
            {
                this.mainTextPanel.RenderTransformOrigin = DefaultRenderCenter;
            }

            if (this.textRotateAngle == 0)
            {
                this.mainTextPanel.RenderTransform = DefaultRotateTransform;
            }
            else
            {
                this.mainTextPanel.RenderTransform = new RotateTransform(textRotateAngle);
            }
        }
        
        #endregion


        #region 其它=========================================================================================================

        //private enum ControlDraggingType { Start, End, None, CenterCP }
        //2012年5月30日已移植并合并至Enums.LineCtrlDraggingType文件中。

        private static DoubleCollection dashArray;

        #endregion
    }
}
